import io
import logging

from django.contrib.auth.models import User
from django.contrib.sessions.serializers import PickleSerializer
from django.http import HttpResponse
from django.shortcuts import render
from django.views  import View
from django_redis import get_redis_connection #导入连接池
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated

from rest_framework.response import Response
from rest_framework.viewsets import GenericViewSet, ReadOnlyModelViewSet, ModelViewSet
from rest_framework_extensions.cache.mixins import CacheResponseMixin

from rest_framework_simplejwt.views import TokenObtainPairView

from config.dbs.redisConfig import KEY_TEMPLATE, EXPIRE_TIME  # 导入redis缓存文件
from users.models import Area, Address
from users.serializers import UserSerializer, MyTokenObtainPairSerializer, UserDetailSerializer, \
    UpdatePasswordSerializer, AreaSerializer, ParentSerializer, AddressSerializer
from utils.verifyUtil import ImageVerify
# Create your views here.
from fdfs_client.client import Fdfs_client,get_tracker_conf
# 创建日志器对象
logger = logging.getLogger(__name__)
# 得到 tracker server
tracker_path = get_tracker_conf("fastdfs/client.conf")
#创建fastdfs客户端
client = Fdfs_client(tracker_path)

class ImageVerifyView(View):

    # 实现验证码视图类
    def get(self, request,func,uuid):
        imageverify = ImageVerify()
        # 调用综合方法
        img,code = imageverify.verify_code()
        # 生成临时字节流文件
        img_bytes= io.BytesIO()
        # 吧图片保存到字节文件中 指定格式为PNG格式
        img.save(img_bytes,format='png')
        img_bytes = img_bytes.getvalue()
        # 设置redis缓存对象
        cache = get_redis_connection(alias="verify_codes")
        # 通过set 写入redis
        cache.set(KEY_TEMPLATE % (f'{func}',uuid),code,EXPIRE_TIME)
        # 图片是二进制数据，所以我们用HttpResponse
        return HttpResponse(img_bytes,content_type='image/png')

# 实现注册的视图集

class UserViewSet(GenericViewSet):
    # 获取查询集
    queryset = User.objects.all()
    # 定义序列化器
    serializer_class = UserSerializer

    # 重写序列化器调用方法
    def get_serializer_class(self):
        if self.action in ["info"]:
            return UserDetailSerializer
        elif self.action == "password":
            return UpdatePasswordSerializer
        else:
            return self.serializer_class

    # 重写 get_permission方法
    def get_permissions(self):
        if  self.action in ["now" ,"info"]:
            permission_classes = [IsAuthenticated]
        else:
            permission_classes = []
        return [permission() for permission in permission_classes]

    # 重写create方法
    def create(self, request, *args, **kwargs):
        # 获取前端数据进行反序列化操作
        serializer = self.get_serializer(data=request.data)
        # 数据校验
        serializer.is_valid(raise_exception=True)
        # 数据校验没有问题 获取用户名和密码
        username = request.data.get('username')
        password = request.data.get('password')

        # 创建user对象 存储数据
        user = User(username=username)
        # 密码加密
        user.set_password(password)
        user.save()

        # 对数据进行序列化 返回创建的用户信息
        return Response(self.get_serializer(user).data)

    @action(methods=['get'],detail=False)
    def now(self,request):
        serializer = self.get_serializer(request.user)
        return Response(serializer.data)

    @action(methods=["put"], detail=False)
    def info(self,request):
        # 得到当前登录的用户信息
        user = request.user
        request.POST._mutable = True # 允许修改post提交数据
        request.data["user"] = user.id
        # 获取客户端传入文件数据
        file = request.FILES.get('file')
        # 判断是否有文件数据
        if file:
            # 是否是图片
            if file.content_type not in ("image/png","image/jpeg","image/gif"):
                return Response(status=status.HTTP_400_BAD_REQUEST)
            # 获取图片后缀
            try:
                image_ext_name = file.name.split('.')[-1]
            except Exception as e:
                logger.info(f"图片扩展名异常{e}")
                image_ext_name = "png"

            try:
                upload_res = client.upload_by_buffer(file.read(),file_ext_name=image_ext_name)
            except Exception as e:
                logger.error(f"图片上传出现未知异常")
                return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR)
            else:
                if upload_res.get("Status") != "Upload successed.":
                    logger.warning("图片上传失败")
                    return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR)
                # 得到文件地址 进行decode解码(地址是b二进制的)
                image_name = upload_res.get("Remote file_id").decode()
                request.data["avatar"] = image_name

        # 判断是否有数据详情
        if hasattr(user,"userdetail"):
            # 以及存在头像 则修改
            if user.userdetail.avatar:
                # 删除之前的头像
                client.delete_file(user.userdetail.avatar.encode())
            user_detail_serializer = self.get_serializer(user.userdetail,data=request.data)
        else:
            user_detail_serializer = self.get_serializer(data=request.data)

        user_detail_serializer.is_valid(raise_exception=True)
        user_detail_serializer.save()
        return Response(user_detail_serializer.data)


    # 密码修改方法
    @action(methods=['put'],detail=False)
    def password(self,request):
        # 获取当前登录的用户
        user = request.user

        # 获取传入的密码  进行反序列化
        serializer = self.get_serializer(data=request.data)
        # 通过is_valid 再序列化器中进行  对象级别校验
        serializer.is_valid(raise_exception=True)
        # 获取新密码
        new_password = request.data["new_password"]
        # 进行密码加密
        user.set_password(new_password)
        user.save()
        return Response({"msg":"密码修改成功"})


# 构建token视图
class MyTokenObtainPairView(TokenObtainPairView):
    serializer_class = MyTokenObtainPairSerializer

# 地区视图集
class AreaViewSet(CacheResponseMixin,ReadOnlyModelViewSet):
    queryset = Area.objects.all()
    serializer_class = AreaSerializer
    permission_classes = [IsAuthenticated]


    # 查询集过滤
    def get_queryset(self):
        if self.action in ["list"]:
            return Area.objects.filter(parent=None)
        else:
            return self.queryset


    # 序列化器过滤
    def get_serializer_class(self):
        if self.action in ["list"]:
            return AreaSerializer
        else:
            return ParentSerializer



# 收货地址视图集
class AddressViewSet(ModelViewSet):
    queryset = Address.objects.all()
    serializer_class = AddressSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        # 获取当前登录的用户
        return self.request.user.address_set.all()

    def create(self, request, *args, **kwargs):
        max_count = 5
        if self.get_queryset().count() > max_count:
            return Response({
                "detail":"收货地址不能超过5个"
            })
        request.POST._mutable = True
        request.data["user"] = str(request.user.id)

        return ModelViewSet.create(self, request, *args, **kwargs)